#include "intersection.h"
#include "adapt_prec_arith.h"
#include <cmath>
#include <math.h>
#include <algorithm>
#include <limits>

segment::segment(double x1_, double y1_, double x2_, double y2_)
{
	x1 = x1_;
	y1 = y1_;
	x2 = x2_;
	y2 = y2_;
}

bool plane(double x1, double x2, double x3, double x4)
{
	return ((std::max(x1, x2) >= std::min(x3, x4)) && (std::max(x3, x4) >= std::min(x1, x2)));
}

bool bound_boxes(segment const& s1, segment const& s2)
{
	return plane(s1.x1, s1.x2, s2.x1, s2.x2) * plane(s1.y1, s1.y2, s2.y1, s2.y2);
}

int left_turn(double a_x, double a_y, double b_x, double b_y, double c_x, double c_y)
{
	double e = 4 * std::numeric_limits<double>::epsilon();
	e *= std::abs((b_x - a_x) * (c_y - a_y)) + std::abs((b_y - a_y) * (c_x - a_x));
	double result = (b_x - a_x) * (c_y - a_y) - (b_y - a_y) * (c_x - a_x);
	if (std::abs(result) > e)
	{
		if (result > 0)
		{
			return 1;
		}
		if (result < 0)
		{
			return -1;
		}
	}
	return left_turn_apa(a_x, a_y, b_x, b_y, c_x, c_y);
}

bool if_intersects(segment const& s1, segment const& s2)
{
	if ((left_turn(s1.x1, s1.y1, s1.x2, s1.y2, s2.x1, s2.y1) * left_turn(s1.x1, s1.y1, s1.x2, s1.y2, s2.x2, s2.y2) > 0) ||
		(left_turn(s2.x1, s2.y1, s2.x2, s2.y2, s1.x1, s1.y1) * left_turn(s2.x1, s2.y1, s2.x2, s2.y2, s1.x2, s1.y2) > 0))
	{
		return false;
	}
	return true;
}

bool has_intersection(segment const& s1, segment const& s2)
{
	if (!bound_boxes(s1, s2))
	{
		return false;
	}
	return if_intersects(s1, s2);
}